package com.maozzi.common.util;

import com.google.gson.Gson;
import com.maozzi.common.enums.BizCodeEnum;
import com.maozzi.common.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.http.HttpStatus;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * HTTP工具类
 *
 * @author maozi
 */
@Slf4j
public class HttpUtil {

    /**
     * 默认字符集：utf-8
     */
    private final static Charset UTF8_CHARSET = StandardCharsets.UTF_8;


    /**
     * gson
     */
    private final static Gson GSON = new Gson();

    /**
     *
     */
    private final static OkHttpClient CLIENT = new OkHttpClient.Builder()
            .connectTimeout(3,TimeUnit.SECONDS)
            .writeTimeout(3,TimeUnit.SECONDS)
            .readTimeout(3,TimeUnit.SECONDS)
            .callTimeout(3, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .build();

    /**
     * get请求
     *
     * @param url     URL
     * @param headers 请求头参数
     * @param params  请求参数
     * @return 结果
     */
    public static String sendGet(String url, Map<String, String> headers, Map<String, String> params) {
        String str;
        Request.Builder builder = new Request.Builder();

        // 设置请求头
        HttpUtil.headerWrap(builder, headers);

        // 设置请求参数，url ? 后边的 k-v 参数
        if (Objects.nonNull(params)) {
            List<String> list = params.entrySet()
                    .stream()
                    .map(entry -> {
                        String paramVal = URLEncoder.encode(entry.getValue(), UTF8_CHARSET);
                        return String.format("%s=%s", entry.getKey(), paramVal);
                    })
                    .collect(Collectors.toList());
            url = String.format("%s?%s", url, String.join("&", list));
        }

        Request request = builder.url(url).get().build();

        // 发送请求
        try (Response response = CLIENT.newCall(request).execute()) {
            // 处理response
            str = HttpUtil.analyzeResponse(response);
        } catch (Exception e) {
            throw new BizException(BizCodeEnum.SERVER_ERROR, e);
        }

        return str;
    }

    /**
     * post请求
     *
     * @param url     url
     * @param headers 请求头参数
     * @param params  参数
     * @return 结果
     */
    public static String sendPost(String url, Map<String, String> headers, Map<String, String> params) {
        String str;
        Request.Builder builder = new Request.Builder();

        // 设置请求头
        HttpUtil.headerWrap(builder, headers);

        // 设置请求参数
        if (Objects.nonNull(params)) {
            String content = GSON.toJson(params);
            RequestBody requestBody = RequestBody.create(
                    content, MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE)
            );
            builder.post(requestBody);
        }

        Request request = builder.url(url).build();

        // 发送请求
        try (Response response = CLIENT.newCall(request).execute()) {
            // 处理response
            str = HttpUtil.analyzeResponse(response);
        } catch (IOException e) {
            throw new BizException(BizCodeEnum.SERVER_ERROR, e);
        }

        return str;
    }

    /**
     * 设置请求头
     *
     * @param builder 请求builder
     * @param headers 请求头参数
     */
    private static void headerWrap(Request.Builder builder, Map<String, String> headers) {
        if (Objects.isNull(builder)) {
            return;
        }

        if (Objects.isNull(headers)) {
            return;
        }

        for (Map.Entry<String, String> entry : headers.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            builder.addHeader(key, value);
        }
    }

    /**
     * 处理response
     *
     * @param response 请求结果
     * @return 返回
     */
    private static String analyzeResponse(Response response) {
        String str = null;
        try {
            if (Objects.isNull(response)) {
                return null;
            }

            boolean successful = response.isSuccessful();
            if (!successful) {
                return null;
            }

            int code = response.code();
            if (HttpStatus.OK.value() != code) {
                return null;
            }

            ResponseBody body = response.body();
            if (Objects.isNull(body)) {
                return null;
            }

            str = body.string();
        } catch (Exception e) {
            log.error("处理response错误", e);
        }

        return str;
    }
}